import {getToken} from "@/utils/auth";
import {EventBus} from "@/utils/eventBus";


const SOCKET_PING_INTERVAL = 5000;
const SOCKET_PING_DATA = '{}';

export class Socket{
  constructor() {
    this.socket = null;
    this.pingIntervalTimer = null;
    this.handleSendMessage = null;
    this.stopForce = false;
    this.reconnectTime = 0;
  }

  isLinking(){
    return this.socket && (this.socket.readyState === WebSocket.OPEN);
  }
  isClosed(){
    return this.socket && this.socket.readyState === WebSocket.CLOSED;
  }
  isConnecting(){
    return this.socket && this.socket.readyState === WebSocket.CONNECTING;
  }


  startWebSocket(){
    if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) {
      console.log('websocket is already open or connecting, continue');
      return;
    }
    console.log('start websocket')
    const scheme = process.env.NODE_ENV === 'production' ? 'wss' : 'ws';
    const socketUrl = process.env.VUE_APP_SOCKET_URL;
    // console.log(socketUrl)
    const token = getToken();
    this.socket = new WebSocket(`${scheme}://${socketUrl}?token=${token}`);

    this.socket.onopen = () => {
      console.log('WebSocket opened');
      // this.ping();
      this.handleOpen();
    };
    this.socket.onmessage = (e) => {
      this.handelMessage(e.data);
    };
    this.socket.onclose = (closeEvent) => {
      console.log('WebSocket closed');
      console.log('closeEvent', closeEvent)

      this.handleClose(closeEvent);
    };

  }
  handleOpen(){

  }
  handelMessage(data){
    let message;
    try {
      message = JSON.parse(data);
    } catch (e) {
      // console.log(data)
      return;
    }
    // console.log(message)

    if (!message?.type) {
      return;
    }
    const type = message.type;
    // 这里处理 PING
    if (type === 'ping') {
      this.sendPingData();
      return;
    }
    switch (type){
      case 'boxScan':
        EventBus.$emit('boxScan', message.data);
        break;
      case 'boxScanFail':
        EventBus.$emit('boxScanFail', message.data);
        break;
      case 'clientError':
        this.stopForce = true
        this.socket.close()
        break;
    }

  }
  handleClose(closeEvent){
    const tryReconnect = () => {
      if (this.socket && this.socket.readyState === WebSocket.CLOSED) {
        console.log('try reconnect');
        setTimeout(()=>{
          this.reconnectTime++
          this.startWebSocket();
        },5000)
      }
    }

    if(!this.stopForce){
      tryReconnect()
    }
    if(this.reconnectTime > 2){
      this.stopForce = true
      this.closeWebSocket()
    }

  }


  ping() {
    clearInterval(this.pingIntervalTimer);
    this.pingIntervalTimer = setInterval(() => {
      this.sendPingData();
    }, SOCKET_PING_INTERVAL);
  }

  sendPingData() {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(SOCKET_PING_DATA);
    }
  }
  // 主动断开连接
  closeWebSocket() {
    this.stopForce = true;
    // this.accountId = null;
    clearInterval(this.pingIntervalTimer);
    if (this.socket) {
      this.socket.close();
    }
    this.socket = null
  }


}
